﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using Dye_CC;
using Dye_Lib;
using System.Reflection;

namespace Dye
{
    public partial class Main : Form
    {
        private Project project;
        private Portaal portaal;
        private SaveFileDialog sFD;
        private OpenFileDialog oFD;
        private TabControl tabControl;
        private int screenOffsetX = 0;
        private int screenOffsetY = 0;
        private bool draggingOffset = false;
        private bool verplaatsOffset = false;

        private int newMousePosX = 0;
        private int newMousePosY = 0;
        private int oldMousePosX = 0;
        private int oldMousePosY = 0;

        private Bitmap currentDiagram;
        private List<string> propNames;
        private string newObject = "Cursor";
        

        public Main()
        {
            InitializeComponent();
            project = Project.Instance;
            portaal = new Portaal();
            sFD = new SaveFileDialog();
            oFD = new OpenFileDialog();

            propNames = new List<string>();
        }

        private void Main_Load(object sender, EventArgs e)
        {
            if (WindowState == FormWindowState.Normal)
                WindowState = FormWindowState.Maximized;
        }

        private void tabPage_Paint(object sender, PaintEventArgs e)
        {
            drawCurrentDiagram();
        }

        private void tabPage_MouseMove(object sender, MouseEventArgs e)
        {
            Main_MouseMove(this, e);
            sslMousePos.Text = string.Format("Mouse: {0}, {1}", e.X - screenOffsetX, e.Y - screenOffsetY);
        }

        private void OpenDiagram(string diagramNaam)
        {
            tabControl.TabPages.Add(new TabPage
            {
                BackColor = System.Drawing.Color.White,
                BorderStyle = System.Windows.Forms.BorderStyle.FixedSingle,
                Location = new System.Drawing.Point(4, 22),
                Padding = new System.Windows.Forms.Padding(3),
                Size = new System.Drawing.Size(800, 600),
                TabIndex = 0,
                Text = diagramNaam,
            });
            TabPage tab = tabControl.TabPages[tabControl.TabPages.Count - 1];
            tab.Paint += new System.Windows.Forms.PaintEventHandler(this.tabPage_Paint);
            tab.MouseMove += new System.Windows.Forms.MouseEventHandler(this.tabPage_MouseMove);
            tab.MouseDown += new System.Windows.Forms.MouseEventHandler(this.tabPage_MouseDown);
            tab.MouseUp += new System.Windows.Forms.MouseEventHandler(this.tabPage_MouseUp);
        }
        
        private void tabPage_MouseUp(object sender, MouseEventArgs e)
        {
            if (e.Button == MouseButtons.Middle)
                draggingOffset = false;
            if (e.Button == MouseButtons.Left)
            {
                verplaatsOffset = false;
                project.PlaatsObject(tabControl.SelectedIndex);
                drawCurrentDiagram();
            }
        }

        private void tabPage_MouseDown(object sender, MouseEventArgs e)
        {

            if (e.Button == MouseButtons.Middle)
                draggingOffset = true;
            if (e.Button == MouseButtons.Left)
            {
                if (newObject == "Cursor")
                {
                    verplaatsOffset = true;
                    pObjects.SelectedObject = project.SelecteerObject(tabControl.SelectedIndex, e.Location,
                        screenOffsetX, screenOffsetY);
                }
                else if (newObject == "Klassediagram")
                {
                    project.AddKlasse(e.X - screenOffsetX, e.Y - screenOffsetY, tabControl.SelectedIndex, "Class");
                }
                drawCurrentDiagram();
            }
        }

        private void Main_MouseMove(object sender, MouseEventArgs e)
        {
            oldMousePosX = newMousePosX;
            oldMousePosY = newMousePosY;
            newMousePosX = e.X;
            newMousePosY = e.Y;

            if (draggingOffset)
            {
                screenOffsetX = screenOffsetX + (newMousePosX - oldMousePosX);
                screenOffsetY = screenOffsetY + (newMousePosY - oldMousePosY);
                sslOffset.Text = string.Format("Offset: {0}, {1}", screenOffsetX, screenOffsetY);

                drawCurrentDiagram();
            }
            else if(verplaatsOffset)
            {
                project.VerplaatsObject(tabControl.SelectedIndex, new Point((newMousePosX - oldMousePosX), (newMousePosY - oldMousePosY)));
                drawCurrentDiagram();
            }
        }

        private void drawCurrentDiagram()
        {           
            currentDiagram = new Bitmap(tabControl.TabPages[tabControl.SelectedIndex].Width, tabControl.TabPages[tabControl.SelectedIndex].Height);
            Graphics g = Graphics.FromImage(currentDiagram);
            g.Clear(Color.White);
            project.Draw(g, tabControl.SelectedIndex, screenOffsetX, screenOffsetY);
            g = tabControl.TabPages[tabControl.SelectedIndex].CreateGraphics();
            g.DrawImage(currentDiagram, new Point(0, 0));            
        }

        private void btnCenter_Click(object sender, EventArgs e)
        {
            screenOffsetX = 0;
            screenOffsetY = 0;
            sslOffset.Text = string.Format("Offset: {0}, {1}", screenOffsetX, screenOffsetY);
            drawCurrentDiagram();
        }

        private void msiNewProject_Click(object sender, EventArgs e)
        {
            int state = portaal.Nieuw(0, 0);
        Begin:
            switch (state)
            {
                case 0://Succes
                    /*
                     * Opmerking ruben: Er verschijnt een lege tabcontrol in de linker bovenhoek, ik heb een stukje code toegevoegd die alleen maar alle tabs verwijderd.
                     * 
                     */
                    // Opmerking marcel: Aangepast ook tevens in de Business Layer.
                    nieuwTabControl();                    
                    break;
                case 1://Vraag: Opslaan?
                    //DialogResult dialogResult = MessageBox.Show(.....);// 0 = None, 1 = Ok, 2 = Cancel, 6 = Yes, 7 = No.
                    state = portaal.Nieuw(1, (int)MessageBox.Show("Wilt u het bestaande Project Opslaan?", "Vraag", MessageBoxButtons.YesNo));
                    goto Begin;
                case 2://SaveFileDialog                  
                    if (UC004())//Ok
                    {
                        MessageBox.Show("Succesvol Opgeslagen");
                        state = portaal.Nieuw(2, 6);
                        goto Begin;
                    }
                    else//Annuleren || x
                    {
                        state = portaal.Nieuw(2, (int)MessageBox.Show("Wilt u alsnog doorgaan?", "Vraag", MessageBoxButtons.YesNo));
                        goto Begin;
                    }
                case 3://Vraag: Doorgaan?
                    state = portaal.Nieuw(2, (int)MessageBox.Show("Wilt u alsnog doorgaan?", "Vraag", MessageBoxButtons.YesNo));
                    goto Begin;
                case 4://Clear Control
                    int index2 = Controls.IndexOf(tabControl);
                    Controls.RemoveAt(index2);
                    tabControl = null;                    
                    state = portaal.Nieuw(0, 0);
                    goto Begin;
                case 5:
                    MessageBox.Show("Geannuleerd");// test
                    break;
                case 6:
                    MessageBox.Show("Error in UC 001");
                    break;
                default:
                    MessageBox.Show("Error in btnNieuw");
                    break;
            }
        }
        private void nieuwTabControl()
        {
            if (tabControl == null)
            {
                tabControl = new TabControl();
                tabControl.Location = pTabFormaat.Location;
                tabControl.Size = pTabFormaat.Size;
                tabControl.Anchor = AnchorStyles.Top | AnchorStyles.Bottom | AnchorStyles.Left | AnchorStyles.Right;
                Controls.Add(tabControl);
                int index = Controls.IndexOf(tabControl);
                Controls[index].BringToFront();
            }
            else MessageBox.Show("Error: nieuwTabControl -> tabControl != null");
        }

        private void msiAddKlassenDiagram_Click(object sender, EventArgs e)
        {
            if (portaal.NieuwDiagram(DiagramType.KlassenDiagram))
            {
                /*
                 * Als het diagram is toegevoegd, moet er ook een extra tabblad komen.
                 * */
                string naam = Microsoft.VisualBasic.Interaction.InputBox("Kies een naam voor uw " + DiagramType.KlassenDiagram.ToString(), "Kies een naam voor uw " + DiagramType.KlassenDiagram.ToString(), DiagramType.KlassenDiagram.ToString() + "(" + (tabControl.TabPages.Count + 1) + ")");
                OpenDiagram(naam);
                portaal.WijzigDiagram(tabControl.TabCount-1, naam);
                
            }
            else
            {
                /*
                 * Als er nog geen project bestaat, moet eerst gevraagd worden om een nieuwe aan te maken.
                 * */
                if (Convert.ToBoolean(MessageBox.Show("U heeft nog geen project geopend, wilt u een nieuw project starten?", "Vraag", MessageBoxButtons.YesNo)))
                {
                    msiNewProject_Click(sender, e);
                    msiAddKlassenDiagram_Click(sender, e);
                }
            }
        }

        private void msiOpslaanProject_Click(object sender, EventArgs e)
        {
            if (UC004()) MessageBox.Show("Succesvol Opgeslagen");//Opslaan
            else MessageBox.Show("Geannuleerd");// test
        }
        private bool UC004()
        {
            int state = portaal.Opslaan(0, 0, "");
        Begin:
            switch (state)
            {
                case 0://begin   
                    //sFD.ShowDialog() == DialogResult << enum                     
                    state = portaal.Opslaan(1, (int)sFD.ShowDialog(), sFD.FileName);
                    goto Begin;
                case 1://success                    
                    return true;
                case 2://annuleerd                    
                    return false;
                case 3://error
                    MessageBox.Show("Error in BU_Opslaan");
                    break;
                default://error
                    MessageBox.Show("Error in btnOpslaan");
                    break;
            }
        return false;
        }

        private void btnAddKlasseTemp_Click(object sender, EventArgs e)
        {
            project = Project.Instance;
            project.Nieuw(0, 0);
            //project.NieuwDiagram(DiagramType.KlassenDiagram);
            //project.AddKlasse(newMousePosX, newMousePosY, tabControl.SelectedIndex, "Class");
            project.AddKlasse(500, 500, tabControl.SelectedIndex, "Class");

            drawCurrentDiagram();
        }

        private void cbDiagram_SelectedIndexChanged(object sender, EventArgs e) {
            switch (cbDiagram.SelectedIndex) {
                case 0:
                    laadKlassediagram();
                    break;
                case 1:
                    laadSequencediagram();
                    break;
                case 2:
                    laadComponentendiagram();
                    break;
                case 3:
                    laadActiviteitendiagram();
                    break;
            }
        }

        private void laadKlassediagram() {
            propNames = new List<string> { "Cursor", "Klassediagram", "Relatie", "Etcetera" };
            itereerDoorDiagrammen(propNames);
        }

        private void laadSequencediagram() {
            propNames = new List<string> { "Componentendiagram", "Relatie", "Etcetera" };
            itereerDoorDiagrammen(propNames);
        }

        private void laadComponentendiagram() {
            propNames = new List<string> { "Klassediagram", "Componentendiagram", "Etcetera" };
            itereerDoorDiagrammen(propNames);
        }

        private void laadActiviteitendiagram() {
            propNames = new List<string> { "Relatie", "Relatie", "Etcetera" };
            itereerDoorDiagrammen(propNames);
        }

        private void itereerDoorDiagrammen(List<string> propNames) {
            lvDiagram.Items.Clear();

            ImageList images = new ImageList();
            List<string> names = new List<string>();

            foreach (PropertyInfo property in typeof(Properties.Resources).GetProperties
                    (BindingFlags.Static | BindingFlags.Public | BindingFlags.NonPublic)) {
                if (property.PropertyType == typeof(Bitmap)) {
                    foreach (string name in propNames) {
                        if (name == property.Name) {
                            var v = property.GetValue(this, null);
                            images.Images.Add((Bitmap)v);
                            names.Add(property.Name);
                        }
                    }
                }
            }

            images.ImageSize = new Size(50, 50);
            lvDiagram.LargeImageList = images;

            int i = 0;
            foreach (string name in names) {
                lvDiagram.Items.Add(name, i);
                i++;
            }
        }

        private void msiOpenProject_Click(object sender, EventArgs e)
        {
            int state = portaal.Openen(0, 0, "");
        Begin:
            switch (state)
            {
                case 0://OpenFileDialog
                    //BU-case 1
                    int laadState = state = portaal.Openen(1, (int)oFD.ShowDialog(), oFD.FileName);
                    if (laadState == 1)//Ok
                    {
                        //Nieuw Method Unpack guiLaadBuffer();
                        MessageBox.Show("Bestand Verwerken");
                        goto Begin;
                    }
                    else//Annuleren || x
                    {                        
                        goto case 5;
                    }
                case 1://succes
                    Laden(); // deze wel! =D
                    //LadenComponenten(1);
                    //tabControl.Visible = true;
                    break;
                case 2://Vraag: Opslaan?
                    state = portaal.Openen(2, (int)MessageBox.Show("Wilt u het bestaande Project Opslaan?", "Vraag", MessageBoxButtons.YesNo), "");
                    goto Begin;
                case 3://UC004                    
                    if (UC004())//Ok
                    {
                        MessageBox.Show("Succesvol Opgeslagen");
                        state = portaal.Openen(3, 6, "");
                        goto Begin;
                    }
                    else//Annuleren || x
                    {
                        goto case 4;
                    }
                case 4://Vraag: Doorgaan?
                    state = portaal.Openen(3, (int)MessageBox.Show("Wilt u alsnog doorgaan?", "Vraag", MessageBoxButtons.YesNo), "");
                    goto Begin;                
                case 5://Geannuleerd
                    MessageBox.Show("Geannuleerd");// test
                    break;
                case 6://Error BU
                    MessageBox.Show("Error in BU_Openen");// test
                    break;
                default://Error GUI
                    MessageBox.Show("Error in btnOpenen");// test
                    break;
            }
        } 
        private void Laden()
        {            
            try
            {
                if (tabControl == null) { nieuwTabControl(); }
                tabControl.TabPages.Clear();
                for (int i = 0; i < project.Diagrammen.Count; i++)
                {                    
                    OpenDiagram(project.Diagrammen[i].Naam + "(" + (tabControl.TabCount + 1) + ")");
                    drawCurrentDiagram();
                }                
            }
            catch
            {
                MessageBox.Show("error: LadenTabs"); 
            }
        }
        //private void LadenComponenten(int index)
        //{
        //    try
        //    {
        //        currentDiagram = new Bitmap(tabControl.TabPages[index].Width, tabControl.TabPages[index].Height);
        //        Graphics g = Graphics.FromImage(currentDiagram);
        //        g.Clear(Color.White);
        //        for (int y = 0; y < currentDiagram.Height; y++)
        //        {
        //            for (int x = 0; x < currentDiagram.Width; x++)
        //            {                   
        //                project.Draw(g, index, screenOffsetX, screenOffsetY);
        //                g = tabControl.TabPages[index].CreateGraphics();
        //                g.DrawImage(currentDiagram, new Point(0, 0));    
        //            }
        //        }
        //    }
        //    catch
        //    {
        //        MessageBox.Show("error: LadenComponenten");
        //    }
        //}

        private void lvDiagram_SelectedIndexChanged(object sender, EventArgs e)
        {
            newObject = propNames[lvDiagram.SelectedIndices[0]];
            
        }

        //als men in het property venster iets aan past word het hier bij gewerkt.
        private void pObjects_PropertyValueChanged(object s, PropertyValueChangedEventArgs e)
        {
            drawCurrentDiagram();
        }
    }
}